package algorithms.sedgewick.part1.percolation;

public class PercolationStats {
	private int N;
	private int T;
	private double[] percolationThresholds;
	private double mean=0.0;
	private double stdDev=0.0;
	private int NSquare;
	public static void main(String[] args) {
		Stopwatch watch = new Stopwatch();
	
		PercolationStats stats = new PercolationStats(200,100);
		stats.printStats();
		System.out.println(watch.elapsedTime());
		/*Percolation perc = new Percolation(2);
		perc.open(1, 1);
		perc.open(2, 2);
		System.out.println(perc.isFull(2, 2));*/

	}
	private void printStats(){
		//System.out.println(String.format("%-24s= %s","mean",mean()));
		System.out.println(String.format("%-24s= %s","stddev",stddev()));
		System.out.println(String.format("%-24s= %s","mean",mean()));
		System.out.println(String.format("%-24s= %s","95% confidence interval",confidenceLo()+", "+confidenceHi()));
	}
	public PercolationStats(int N, int T) {
		validateInput(N,T);
		this.N=N;
		this.T=T;
		this.NSquare = N*N;
		this.percolationThresholds = new double[T];
	}

	private void validateInput(int N, int T) {
		if(N<=0 || T<=0){
			throw new IllegalArgumentException();
		}
	}
	public double mean(){
		if(mean!=0.0)
			return mean;
		Percolation percolation;
		int openSiteCount;
		int repetitions = 0;
		int i=0,j=0;
		int rand=0;
		double sum=0.0;
		while(repetitions<T){
			openSiteCount=0;;
			percolation = new Percolation(N);
			while(!percolation.percolates()){
				rand=StdRandom.uniform(0, NSquare);
				i=rand/N;
				j=rand-i*N;
				i++;
				j++;
				if(!percolation.isOpen(i, j)){
					//System.out.println("Opening Site:("+i+","+j+")");
					//openSiteCount++;
					percolation.open(i, j);
				}
			}
			for(int k=1;k<=N;k++){
				for(int l=1;l<=N;l++){
					if(percolation.isOpen(k, l)){
						openSiteCount++;
					}
				}
			}
			//System.out.println("D");
			percolationThresholds[repetitions++] = openSiteCount/(double)NSquare;
		}
		for(double threshold:percolationThresholds){
			sum+=threshold;
		}
		return mean=sum/T;
	}

	public double stddev() {
		if(stdDev!=0.0)
			return stdDev;
		double squareSum=0.0;
		if(mean==0.0){
			mean = mean();
		}
		double diff;
		for(double threshold:percolationThresholds){
			diff=(threshold-mean);
			squareSum+=diff*diff;
		}
		return stdDev = Math.sqrt(squareSum/(T-1));
	}
	public double confidenceLo(){
		if(stdDev==0.0){
			stdDev=stddev();
		}
		return mean-(1.96*stdDev/Math.sqrt(T));

	}
	public double confidenceHi()     {
		if(stdDev==0.0){
			stdDev=stddev();
		}
		return mean+(1.96*stdDev/Math.sqrt(T));
	}

}
